from bst import BiTreeNode, BST


class AVLNode(BiTreeNode):
    def __init__(self, data):
        BiTreeNode.__init__(self, data)
        self.bf = 0


class AVLTree(BST):
    def __init__(self, li=None):
        BST.__init__(self, li)

    # 左旋
    def rotate_left(sel, p, c):
        s2 = c.lchild
        p.rchild = s2
        if s2:
            s2.parent = p
        c.lchild = p
        p.parent = c

        p.bf = 0
        c.bf = 0
        return c

    # 右旋
    def rotate_right(self, p, c):
        s2 = c.rchild
        p.lchild = s2

        # 判断c是否有右孩子
        if s2:
            s2.parent = p
        c.rchild = p
        p.parent = c

        # 更新balance factor
        p.bf = 0
        c.bf = 0
        return c

    #先左旋在右旋
    def rotate_right_left(self,p,c):
        g=c.lchild
        s2=g.lchild
        p.rchild=s2
        if s2:
            s2.parent=p
        g.rchild=c
        c.parent=g

        s3=g.rchild
        c.lchild=s3
        if s3:
            s3.parent=c
        g.lchild=p
        p.parent=g

        #更新bf
        if g.bf>0:
            c.bf=0
            p.bf=-1
        else:
            p.bf=0
            c.bf=1
        g.bf=0
        return g

    def rotate_left_right(self,p,c):
        g=c.rchild
        s2=g.lchild
        c.rchild=s2
        if s2:
            s2.parent=c
        g.lchild=c
        c.parent=g

        s3=g.rchild
        p.lchild=s3
        if s3:
            s3.parent=p
        g.rchild=p
        p.parent=g

        #更新bf

        if g.bf>0:
            p.bf=0
            c.bf=-1
        else:
            p.bf=1
            c.bf=0
        g.bf=0
        return g
    #插入
    def insert_no_rec(self,val):
        #1、和BST一样，插入
        p = self.root
        # 空值时进行特殊处理
        if not p:
            self.root = AVLNode(val)
            return
        while True:
            if val < p.data:
                if p.lchild:
                    p = p.lchild
                else:  # 左子树不存在
                    p.lchild = AVLNode(val)
                    p.lchild.parent = p
                    node=p.lchild #node存储的是插入的节点
                    break
            elif val > p.data:
                if p.rchild:
                    p = p.rchild
                else:  # 右子树不存在
                    p.rchild = BiTreeNode(val)
                    p.rchild.parent = p
                    node=p.rchild
                    break
            else: #val==node.data
                return

            #2、更新balance factor
        while node.parent: #node.parent存在
            if node.parent.lchild==node: #传递是从左子树来的，左子树更沉
                #更新node.parent的bf-=1
                if node.parent.bf<0: #原来node.parent.bf==-1，更新后变成-2
                    #做旋转
                    #看node哪边沉
                    g=node.parent.parent #为了链接旋转之后的子树
                    x=node.parent #旋转前子树的根
                    if node.bf>0:
                        n=self.rotate_left_right(node.parent,node)
                    else:
                        n=self.rotate_right(node.parent,node)
                    #记得把n和g连起来

                elif node.parent.bf>0: #原来node.parent.bf=1,更新之后变为0
                    node.parent.bf=0
                    break
                else: #原来的node.parent.bf=0,更新之后变为-1
                    node.parent.bf=-1
                    node=node.parent
                    continue
            else: #传递是从右子树来的，右子树更沉
                #更新后的node.parent.bf+=1
                if node.parent.bf>0: #说明原来的node.parent.bf==1,更新后变为2
                    #坐旋转
                    #看node哪边沉
                    g=node.parent.parent
                    x=node.parent
                    if node.bf<0: #node左边沉,node.bf=-1
                        n=self.rotate_right_left(node.parent,node)
                    else: #node.bf=1
                        n=self.rotate_left(node.parent,node)
                    #记得连起来
                elif node.parent.bf<0: #原来的node.parent.bf=-1，更新后变为0
                    node.parent.bf=0
                    break
                else:   #原来的node.parent.bf=0，更新后变为1
                    node.parent.bf=1
                    node=node.parent
                    continue

            #链接旋转后的子树
            n.parent=g
            if g: #如果g不是空
                if x==g.lchild:
                    g.lchild=n
                else:
                    g.rchild=n
                break

            else:
                self.root=n
                break

tree=AVLTree([9,8,7,6,5,4,3,2,1])
tree.pre_order(tree.root)
print('')
tree.in_order(tree.root)
